package tech.wetech.admin.modules.system.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ccb.CCBMisSdk;
import com.ccbft.pos.service.mis.Config;
import com.ccbft.pos.service.mis.enums.TransRequestEnum;
import com.ccbft.pos.service.mis.model.api.MisApiHttpVo;
import com.ccbft.pos.service.mis.model.api.MisApiResponseVo;
import com.ccbft.pos.service.mis.util.CCBMisSdkUtils;
import com.ccbft.pos.service.mis.util.JsonUtil;
import com.ccbft.pos.service.mis.util.KeyUtilsBean;
import com.ccbft.pos.service.mis.util.RequestService;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import tech.wetech.admin.core.exception.BizException;
import tech.wetech.admin.core.utils.ResultCodeEnum;
import tech.wetech.admin.modules.system.mapper.PayCompanyInfoMapper;
import tech.wetech.admin.modules.system.po.CCBSKRequest;
import tech.wetech.admin.modules.system.po.PayCompanyInfo;
import tech.wetech.admin.modules.system.service.CCBPayService;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @description 建行
 * @date 2019年09月05日 14:11
 */
@Service
@Slf4j
public class CCBPayServiceImpl implements CCBPayService {

  @Autowired
  private RedisTemplate redisTemplate;

  @Autowired
  private StringRedisTemplate stringRedisTemplate;

  @Autowired
  private PayCompanyInfoMapper payCompanyInfoMapper;


  /**
   * 下载建行秘钥.授权码做为key存到redis里面去。
   *
   * @param request
   * @return
   */
  @Override
  public Map<String, String> downloadSecretKey(CCBSKRequest request) {
    String redisKey = "ccb:authcode:" + request.getAuthCode();

    // 使用 StringRedisSerializer 序列化和反序列化键值
    StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
    // 设置键序列化方式
    redisTemplate.setKeySerializer(stringRedisSerializer);
    // 设置值序列化方式，可以是 Jackson2JsonRedisSerializer 或其他
    redisTemplate.setValueSerializer(stringRedisSerializer);
    // 设置键的反序列化方式
    redisTemplate.setKeySerializer(stringRedisSerializer);
    // 设置值的反序列化方式
    redisTemplate.setValueSerializer(stringRedisSerializer);

    redisTemplate.setHashKeySerializer(stringRedisSerializer);
    redisTemplate.setHashValueSerializer(stringRedisSerializer);

    redisTemplate.afterPropertiesSet();

    Map<String, String> resultMap = (Map<String, String>) redisTemplate.opsForHash().entries(redisKey);
    if (!ObjectUtils.isEmpty(resultMap)) {
      return resultMap;
    }

    resultMap.put("mchtNo", request.getMchtNo());
    resultMap.put("termNo", request.getTermNo());
    resultMap.put("authCode", request.getAuthCode());
    resultMap.put("podId", request.getPosId());

    //向建行发送请求

    System.out.println("交易码：" + TransRequestEnum.AU011);
    //构建请求参数
    MisApiHttpVo misApiHttpVo = new MisApiHttpVo(TransRequestEnum.AU011, request.getMchtNo(), request.getTermNo(), request.getTermNo());

    KeyUtilsBean misBankKey = CCBMisSdkUtils.getKeyUtilsBean();
    misApiHttpVo.setPublicKey(misBankKey.getPublicKey());
    misApiHttpVo.setAuthCode(request.getAuthCode());

    resultMap.put("publicKey", misBankKey.getPublicKey());
    resultMap.put("privateKey", misBankKey.getPrivateKey());

    //加密参数
    System.out.println("misApiHttpVo：" + JsonUtil.toJsonString(misApiHttpVo));

    //发送请求
    String result = new RequestService().sendJsonPost(Config.url, null, JsonUtil.toJsonString(misApiHttpVo));
    System.out.println("result：" + result);

    //json转对象
    MisApiResponseVo misApiResponse = JsonUtil.jsonStringToObject(result, new TypeReference<MisApiResponseVo>() {
    });
    if ("00".equals(misApiResponse.getRetCode())) {
      //解密数据
      String key = CCBMisSdk.CCBMisSdk_KeyDecrypt(misApiResponse.getKey(), misBankKey.getPrivateKey());
      System.out.println(key);
      resultMap.put("key", key);
      redisTemplate.opsForHash().putAll(redisKey, resultMap);
      return resultMap;
    } else {
      //请求失败
      System.out.println(misApiResponse.getRetErrMsg());
      throw new BizException(ResultCodeEnum.NOT_IMPLEMENTED);
    }

  }

  /**
   * 更新秘钥
   *
   * @param companyId
   * @return
   */
  public Map<String, String> updateSecretKey(String companyId) throws InterruptedException {
    PayCompanyInfo info = payCompanyInfoMapper.selectByCompanyId(companyId);
    log.info(JSON.toJSONString(info));
    JSONObject jsonObject = JSON.parseObject(info.getPayJson());

    String oldKey = jsonObject.getString("scan_key");
    String mchtCode = jsonObject.getString("scan_mchtNo");
    String terminalId = jsonObject.getString("scan_termNo");
    String termSN = jsonObject.getString("scan_posId");

    String newKey = getKey(oldKey, mchtCode, terminalId, termSN);

    if (StringUtils.isEmpty(newKey)) {
      System.out.println("授权[" + TransRequestEnum.AU012 + "]交易失败");
      throw new BizException(ResultCodeEnum.CCB_GETSK_FAILED);
    } else {
      System.out.println("授权[" + TransRequestEnum.AU012 + "]交易成功");
    }

    int sum = 5;
    int count = 0;

    boolean state = false;
    while (!state && count < sum) {
      try {
        state = confirmUpdate(newKey, mchtCode, terminalId, termSN);
      } catch (Exception e) {
        e.printStackTrace();
      }
      if (!state) {
        Thread.sleep(5 * 1000);
      }
      count++;
      System.out.println(count);
    }

    if (state) {
      System.out.println("授权[" + TransRequestEnum.AU013 + "]交易成功");
      jsonObject.put("scan_key", newKey);
      payCompanyInfoMapper.updatePayJsonById(info.getId(), jsonObject.toJSONString());
    } else {
      System.out.println("授权[" + TransRequestEnum.AU013 + "]交易失败");
      throw new BizException(ResultCodeEnum.CCB_CONFIRM_SK_FAILED);
    }

    log.info("newKey:{}", newKey);
    Map<String, String> result = new HashMap<>();
    result.put("key", newKey);
    deleteRedis();
    return result;
  }


  /**
   * 建行更新秘钥
   *
   * @return
   */
  private String getKey(String key, String mchtCode, String terminalId, String termSN) {
    log.info("交易码:{}", TransRequestEnum.AU012);
    //构建请求参数
    MisApiHttpVo misApiHttpVo = new MisApiHttpVo(TransRequestEnum.AU012, mchtCode, terminalId, termSN);
    KeyUtilsBean misBankKey = CCBMisSdkUtils.getKeyUtilsBean();
    misApiHttpVo.setPublicKey(misBankKey.getPublicKey());
    misApiHttpVo.sign(misBankKey.getPrivateKey(), key);
    //加密参数
    System.out.println("misApiHttpVo：" + JsonUtil.toJsonString(misApiHttpVo));

    //发送请求
    String result = new RequestService().sendJsonPost(Config.url, null, JsonUtil.toJsonString(misApiHttpVo));
    System.out.println("result：" + result);

    //json转对象
    MisApiResponseVo misApiResponse = JsonUtil.jsonStringToObject(result, new TypeReference<MisApiResponseVo>() {
    });
    if ("00".equals(misApiResponse.getRetCode())) {
      //解密数据
      System.out.println(CCBMisSdk.CCBMisSdk_KeyDecrypt(misApiResponse.getKey(), misBankKey.getPrivateKey()));
      return CCBMisSdk.CCBMisSdk_KeyDecrypt(misApiResponse.getKey(), misBankKey.getPrivateKey());
    } else {
      //请求失败
      System.out.println(misApiResponse.getRetErrMsg());
    }
    return null;
  }

  private boolean confirmUpdate(String key, String mchtCode, String terminalId, String termSN) {
    System.out.println("交易码：" + TransRequestEnum.AU013);
    //构建请求参数
    MisApiHttpVo misApiHttpVo = new MisApiHttpVo(TransRequestEnum.AU013, mchtCode, terminalId, termSN);
    KeyUtilsBean misBankKey = CCBMisSdkUtils.getKeyUtilsBean();
    misApiHttpVo.setPublicKey(misBankKey.getPublicKey());
    misApiHttpVo.sign(misBankKey.getPrivateKey(), key);
    //加密参数
    System.out.println("misApiHttpVo：" + JsonUtil.toJsonString(misApiHttpVo));

    //发送请求
    String result = new RequestService().sendJsonPost(Config.url, null, JsonUtil.toJsonString(misApiHttpVo));
    System.out.println("result：" + result);

    //json转对象
    MisApiResponseVo misApiResponse = JsonUtil.jsonStringToObject(result, new TypeReference<MisApiResponseVo>() {
    });
    if ("00".equals(misApiResponse.getRetCode())) {
      //解密数据
      System.out.println(misApiResponse.getRetErrMsg());
      return true;
    } else {
      //请求失败
      System.out.println(misApiResponse.getRetErrMsg());
      return false;
    }
  }

  /**
   * 删除redis的支付配置相关的
   *
   * @return
   */
  private boolean deleteRedis() {

    Set<String> keys = stringRedisTemplate.keys("*");
    Long result = stringRedisTemplate.delete(keys);
    return true;
  }


}
